/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gui;

import static gui.GUIUtils.initTextHeaderJlabel;
import static gui.GUIUtils.listToString;
import static gui.JPanelBookInfo.CLOSE_PANEL_HEIGHT;

import gui.utilities.Rater;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.io.IOException;
import java.net.URISyntaxException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import javax.swing.JOptionPane;

import core.exceptions.DBAccessException;
import core.objects.Book;
import core.objects.BookLoan;
import core.objects.User;
import core.objects.enums.LoanStatusEnum;
import db.DBAccessEngine;
import db.IDBAccess;
import db.MySQLFormatDate;

/**
 *
 * @author abadi
 */
public class JPanelBookInfoForUsersBookSearch extends javax.swing.JPanel {
    public static final String DONT_HAVE_IT =     "<html><u>[Remove from My-Books]</u></html>";
    public static final String ADD_TO_MY_BOOKS = "<html><u>[Add to My-Books]</u></html>";
    public static final String AVAILABLE = "Available";

    private Rater usersRater;
    private Book book;
    private User owner;

    /**
     * Creates new form jPanelBookInfoHeaderWithPic
     */
    public JPanelBookInfoForUsersBookSearch(Book book, User owner) {
        this(book, owner, true);
    }

    /**
     * Creates new form jPanelBookInfoHeaderWithPic
     */
    public JPanelBookInfoForUsersBookSearch(Book book, User owner, boolean isLoanItVisible) {
        this.book = book;
        this.owner = owner;
        initComponents();
        initHeaderComponents();
        setVisible(false);
        setVisible(true);
        if (!isLoanItVisible || owner.getID() == MainForm.
                getMyUser().getID()) {
            jLabelLoanIt.setEnabled(false);
            jLabelLoanIt.setVisible(false);
        }
        setMaximumSize(new Dimension(Integer.MAX_VALUE, CLOSE_PANEL_HEIGHT));
        setPreferredSize(new Dimension(getWidth(), CLOSE_PANEL_HEIGHT));
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this
     * code. The content of this method is always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanelBookHeader = new javax.swing.JPanel();
        jLabelAuthor = new javax.swing.JLabel();
        jLabelPublisher = new javax.swing.JLabel();
        jLabelCategory = new javax.swing.JLabel();
        jLabelPublicationYear = new javax.swing.JLabel();
        jLabelCategoryPageCount = new javax.swing.JLabel();
        jLabelISBN = new javax.swing.JLabel();
        jPanelBookTitle = new javax.swing.JPanel();
        jLabelBookName = new javax.swing.JLabel();
        jLabelWiki = new javax.swing.JLabel();
        jLabelEnlarge = new javax.swing.JLabel();
        jLabelStatus = new javax.swing.JLabel();
        jLabelLoanIt = new javax.swing.JLabel();
        jLabelAddToMyBooks = new javax.swing.JLabel();
        jPanelRating = new javax.swing.JPanel();
        jLabelImage = new javax.swing.JLabel();

        setBackground(new java.awt.Color(51, 153, 255));
        setBorder(javax.swing.BorderFactory.createEtchedBorder());
        setOpaque(false);

        jPanelBookHeader.setOpaque(false);

        jLabelAuthor.setText("Author:");

        jLabelPublisher.setText("Publisher:");

        jLabelCategory.setText("Category: ");

        jLabelPublicationYear.setText("Publication Year: ");

        jLabelCategoryPageCount.setText("Page Count: ");

        jLabelISBN.setText("ISBN: ");

        jPanelBookTitle.setOpaque(false);

        jLabelBookName.setText("Book Name");

        jLabelWiki.setText("[Wiki]");

        jLabelEnlarge.setText("[+]");
        jLabelEnlarge.setToolTipText("Sounds Interesting...");
        jLabelEnlarge.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
			public void mouseClicked(java.awt.event.MouseEvent evt) {
                jLabelEnlargeMouseClicked(evt);
            }
        });

        jLabelLoanIt.setText("[Loan It]");
        jLabelLoanIt.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
			public void mouseClicked(java.awt.event.MouseEvent evt) {
                jLabelLoanItMouseClicked(evt);
            }
        });

        jLabelAddToMyBooks.setText("[Add to My-Books]");
        jLabelAddToMyBooks.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
			public void mouseClicked(java.awt.event.MouseEvent evt) {
                jLabelAddToMyBooksMouseClicked(evt);
            }
        });

        javax.swing.GroupLayout jPanelBookTitleLayout = new javax.swing.GroupLayout(jPanelBookTitle);
        jPanelBookTitle.setLayout(jPanelBookTitleLayout);
        jPanelBookTitleLayout.setHorizontalGroup(
            jPanelBookTitleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelBookTitleLayout.createSequentialGroup()
                .addComponent(jLabelEnlarge)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabelBookName, javax.swing.GroupLayout.DEFAULT_SIZE, 255, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabelStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 68, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabelWiki)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabelAddToMyBooks)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabelLoanIt)
                .addGap(136, 136, 136))
        );
        jPanelBookTitleLayout.setVerticalGroup(
            jPanelBookTitleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jLabelStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGroup(jPanelBookTitleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(jLabelBookName)
                .addComponent(jLabelWiki)
                .addComponent(jLabelEnlarge)
                .addComponent(jLabelLoanIt)
                .addComponent(jLabelAddToMyBooks, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanelRating.setOpaque(false);
        jPanelRating.setLayout(new java.awt.GridLayout(1, 1));

        javax.swing.GroupLayout jPanelBookHeaderLayout = new javax.swing.GroupLayout(jPanelBookHeader);
        jPanelBookHeader.setLayout(jPanelBookHeaderLayout);
        jPanelBookHeaderLayout.setHorizontalGroup(
            jPanelBookHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelBookHeaderLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanelBookHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanelBookHeaderLayout.createSequentialGroup()
                        .addComponent(jPanelBookTitle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 0, 0)
                        .addComponent(jPanelRating, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanelBookHeaderLayout.createSequentialGroup()
                        .addGroup(jPanelBookHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabelAuthor, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jLabelPublisher, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanelBookHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabelCategoryPageCount, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jLabelISBN, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanelBookHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabelCategory, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jLabelPublicationYear, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                .addContainerGap())
        );
        jPanelBookHeaderLayout.setVerticalGroup(
            jPanelBookHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelBookHeaderLayout.createSequentialGroup()
                .addGroup(jPanelBookHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanelRating, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(jPanelBookHeaderLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jPanelBookTitle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanelBookHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabelAuthor)
                    .addComponent(jLabelCategory)
                    .addComponent(jLabelCategoryPageCount))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanelBookHeaderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabelPublisher)
                    .addComponent(jLabelPublicationYear)
                    .addComponent(jLabelISBN))
                .addContainerGap())
        );

        jLabelImage.setAlignmentY(0.0F);
        jLabelImage.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 51, 51), 1, true));
        jLabelImage.setMaximumSize(new java.awt.Dimension(20, 2));
        jLabelImage.setPreferredSize(new java.awt.Dimension(2, 90));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabelImage, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanelBookHeader, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabelImage, javax.swing.GroupLayout.DEFAULT_SIZE, 98, Short.MAX_VALUE)
                    .addComponent(jPanelBookHeader, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void jLabelEnlargeMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabelEnlargeMouseClicked
        MainForm.searchForBooks(book);
    }//GEN-LAST:event_jLabelEnlargeMouseClicked

    private void jLabelLoanItMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabelLoanItMouseClicked
        if (insertNewLoan(owner, MainForm.getMyUser(), book)) {
            updateStatusLabel(LoanStatusEnum.Ongoing);
            try {
                String authorsString = GUIUtils.listToString(book.getAuthors());
                GUIUtils.mailto(owner.getEmail(), "Loan " + book.getName(), "Hi there, " + owner.getName() + "!\nI would like to coordinate with you the loan of " + book.getName() + (authorsString != null ? " by " + authorsString : "") + ".\nPlease contact me.\nRegards, \n" + MainForm.getMyUser().getName());
            } catch (IOException | URISyntaxException ex) {
                JOptionPane.showMessageDialog(this, "Loan-a-Book failed to open your email client.", "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }//GEN-LAST:event_jLabelLoanItMouseClicked

    private void jLabelAddToMyBooksMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabelAddToMyBooksMouseClicked
        if (!jLabelAddToMyBooks.isEnabled()) return;
        if (!jLabelAddToMyBooks.getText().equals(DONT_HAVE_IT)) {
            addBookToMyList(book);
            switchAddWithRemove();
            jLabelLoanIt.setEnabled(false);
        }else if (jLabelStatus.getText().trim().equals(AVAILABLE)){
            removeFromMyBooksList(book);
            switchAddWithRemove();
            jLabelLoanIt.setEnabled(true);
        }
    }//GEN-LAST:event_jLabelAddToMyBooksMouseClicked
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabelAddToMyBooks;
    private javax.swing.JLabel jLabelAuthor;
    private javax.swing.JLabel jLabelBookName;
    private javax.swing.JLabel jLabelCategory;
    private javax.swing.JLabel jLabelCategoryPageCount;
    private javax.swing.JLabel jLabelEnlarge;
    private javax.swing.JLabel jLabelISBN;
    private javax.swing.JLabel jLabelImage;
    private javax.swing.JLabel jLabelLoanIt;
    private javax.swing.JLabel jLabelPublicationYear;
    private javax.swing.JLabel jLabelPublisher;
    private javax.swing.JLabel jLabelStatus;
    private javax.swing.JLabel jLabelWiki;
    private javax.swing.JPanel jPanelBookHeader;
    private javax.swing.JPanel jPanelBookTitle;
    private javax.swing.JPanel jPanelRating;
    // End of variables declaration//GEN-END:variables

    private void initHeaderComponents() {
        jLabelBookName.setText("<html><u>" + book.getName() + "</u></html>");
        //bookPanel(book);
        if (book.getThumbnailURL() != null) {
            GUIUtils.setImageAtSize(jLabelImage, 60, 90, book.getThumbnailURL());
        } else {
            GUIUtils.setImageAtSize(jLabelImage, 60, 90, "/resources/book.png");
        }
        GUIUtils.setJComponentFontAndColor(jLabelBookName, 15);

        initTextHeaderJlabel(jLabelAuthor, listToString(book.getAuthors()));
        initTextHeaderJlabel(jLabelCategory, listToString(book.getCategories()));
        initTextHeaderJlabel(jLabelCategoryPageCount, book.getNumOfPages() + "");
        initTextHeaderJlabel(jLabelISBN, book.getISBN());
        initTextHeaderJlabel(jLabelPublicationYear,
                MySQLFormatDate.getYearString(book.getReleaseYear()));
        initTextHeaderJlabel(jLabelPublisher, listToString(book.getPublishers()));

        GUIUtils.setJComponentFontAndColor(jLabelStatus, 13);
        updateStatusLabel();
        GUIUtils.setURLLink(jLabelAddToMyBooks, null, true);
        GUIUtils.setURLLink(jLabelWiki, book.getWikipediaURL(), true);
        GUIUtils.setURLLink(jLabelLoanIt, null, false);
        GUIUtils.setURLLink(jLabelEnlarge, null, false);
        
        int voters = 0;
        double rating = 0;
        try {
            voters = DBAccessEngine.BookComment().selectCount(book.getID(), new Book(0, ""));
            rating = DBAccessEngine.BookComment().selectAvg(book.getID());
        } catch (DBAccessException ex) {
            GUIUtils.showMessageError(ex, this);
        }
        usersRater = new Rater(((int) Math.round(rating)), voters);
        usersRater.setEnabled(false);
        jPanelRating.add(usersRater);
        
        if (disableAddToBooksIOwn()) {
            return;
        }
    }

    @SuppressWarnings("unchecked")
	public static LoanStatusEnum checkBookStatus(Book book, User user) {
        //TODO: save this list as a class member.
        List<BookLoan> loans = null;
        try {
            loans = (List<BookLoan>) DBAccessEngine.BookLoan().select(user.getID()); // all book that user has loaned
        } catch (DBAccessException ex) {
            GUIUtils.showMessageError(ex, new Component() {
            });
        }

        if (loans != null) {
	        for (BookLoan loan : loans) {
	            if (loan.getBookId() == book.getID()) {
	                return loan.getStatus();
	            }
	        }
	    }
        return null;
    }

    @SuppressWarnings("unchecked")
	public static boolean insertNewLoan(User loaner, User loanedTo, Book book) {
        try {
            Timestamp now = new Timestamp(new Date().getTime());
            BookLoan bookLoan = new BookLoan(0, book.getID(), loaner.getID(),
                    loanedTo.getID(), now, null, LoanStatusEnum.Ongoing);
            ((IDBAccess<BookLoan>) DBAccessEngine.BookLoan()).insert(bookLoan);
            return true;
        } catch (DBAccessException ex) {
            GUIUtils.showMessageError(ex, null);
            return false;
        }
    }

    private void updateStatusLabel() {
        LoanStatusEnum bookStatus = checkBookStatus(book, owner);
        updateStatusLabel(bookStatus);
    }

    private void updateStatusLabel(LoanStatusEnum bookStatus) {
        if (bookStatus == null) {
            initTextHeaderJlabel(jLabelStatus, AVAILABLE);
        } else {
            jLabelStatus.setText(bookStatus.toString());
            jLabelStatus.setForeground(Color.RED);
            jLabelLoanIt.setEnabled(false);
        }
    }

    @SuppressWarnings("unchecked")
	private void addBookToMyList(Book book) {
        try {
            ((IDBAccess<User>) DBAccessEngine.User()).insert(MainForm.getMyUser(), book);
        } catch (DBAccessException ex) {
            GUIUtils.showMessageError(ex, this);
        }
    }

    @SuppressWarnings("unchecked")
	private boolean disableAddToBooksIOwn() {
        List<Book> books;
        try {
            books = (List<Book>) DBAccessEngine.User().selectAll(MainForm.getMyUser().getID(), new Book(0, ""));
            for (Book b : books) {
                if (b.getID() == book.getID()) {
                    switchAddWithRemove();
                    return true;
                }
            }
        }catch (DBAccessException ex) {
           GUIUtils.showMessageError(ex, this);
       }return false;
    }

    private void switchAddWithRemove() {
        if (jLabelAddToMyBooks.getText().equals(DONT_HAVE_IT))
            jLabelAddToMyBooks.setText(ADD_TO_MY_BOOKS);
        else{
            jLabelAddToMyBooks.setText(DONT_HAVE_IT);
            if (!jLabelStatus.getText().trim().equals(AVAILABLE)){
                jLabelAddToMyBooks.setEnabled(false);
                jLabelAddToMyBooks.setForeground(Color.GRAY);
            }
        }
    }

    @SuppressWarnings("unchecked")
	private void removeFromMyBooksList(Book book) {
        try {
            ((IDBAccess<User>) DBAccessEngine.User()).delete(MainForm.getMyUser(), book);
        } catch (DBAccessException ex) {
            GUIUtils.showMessageError(ex, this);
        }
    }
}